home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.3 Development Libraries / SGI IRIX 6.3 Development Libraries.iso / dist6.3 / gl_dev.idb / usr / share / src / OpenGL / teach / motif / switch-visual.c.z / switch-visual.c
Encoding:
C/C++ Source or Header  |  1996-12-06  |  9.4 KB  |  316 lines

  1. /*
  2.  * animate.c - double buffered RGBA motif program with a work proc for animation
  3.  */
  4. /* compile: cc -o animate animate.c -lGLw -lGLU -lGL -lXm -lXt -lX11 */
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <Xm/Frame.h>
  8. #include <Xm/Form.h>
  9. #include <Xm/RowColumn.h>
  10. #include <X11/GLw/GLwMDrawA.h>
  11. #include <X11/keysym.h>
  12. #include <X11/Xutil.h>
  13. #include <GL/glx.h>
  14. #include <GL/glu.h>
  15.  
  16. static void draw_scene(Widget w, Boolean advance);
  17. static void initialize(void);
  18. static Boolean redraw_proc(XtPointer clientData);
  19.  
  20. static int db_attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None};
  21. static int sb_attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, None};
  22.  
  23. static String fallbackResources[] = {
  24.     "*sgiMode: True",
  25.     "*useSchemes: all",
  26.     "*single.width: 300", "*single.height: 300",
  27.     "*double.width: 300", "*double.height: 300",
  28.     "*frame.shadowType: SHADOW_IN",
  29.     NULL};
  30.  
  31. static struct {            /* global UI variables - keep them together */
  32.     XtAppContext appctx;
  33.     Widget sw, dw;        /* single & double buffered widgets */
  34.     GLXContext scx, dcx;    /* single & double buffered contexts */
  35.     Boolean single;        /* single buffered */
  36.     Boolean direct;
  37.     Dimension width, height;    /* dimensions for viewport */
  38.     XtWorkProcId animate_wpid;
  39. } state;
  40.  
  41. static void
  42. input(Widget w, XtPointer client_data, XtPointer call) {
  43.     char buf[31];
  44.     KeySym keysym;
  45.     XEvent *event = ((GLwDrawingAreaCallbackStruct *) call)->event;
  46.  
  47.     switch(event->type) {
  48.     case KeyRelease:
  49.     XLookupString(&event->xkey, buf, sizeof buf, &keysym, NULL);
  50.     switch(keysym) {
  51.     case XK_Escape:
  52.         exit(EXIT_SUCCESS);
  53.         break;
  54.     default: break;
  55.     }
  56.     break;
  57.     }
  58. }
  59.  
  60. static void
  61. resize(Widget w, XtPointer client_data, XtPointer call) {
  62.     GLwDrawingAreaCallbackStruct *call_data;
  63.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  64.  
  65.     glViewport(0, 0, call_data->width, call_data->height);
  66.     state.width = call_data->width; state.height = call_data->height;
  67. }
  68.  
  69. static void
  70. expose(Widget w, XtPointer client_data, XtPointer call) {
  71.     GLwDrawingAreaCallbackStruct *call_data;
  72.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  73.  
  74.     draw_scene(w, False);
  75. }
  76.  
  77. static void
  78. submenu(Widget w, XtPointer clientData, XtPointer callData) {
  79.     int entry = (int) clientData;
  80.  
  81.     switch (entry) {
  82.     case 0:
  83.     XtManageChild(state.sw);
  84.     XRaiseWindow(XtDisplay(state.sw), XtWindow(state.sw));
  85.     GLwDrawingAreaMakeCurrent(state.sw, state.scx);
  86.     glViewport(0, 0, state.width, state.height);
  87.     state.single = True;
  88.     XtUnmanageChild(state.dw);
  89.     break;
  90.     case 1:
  91.     XtManageChild(state.dw);
  92.     XRaiseWindow(XtDisplay(state.dw), XtWindow(state.dw));
  93.     GLwDrawingAreaMakeCurrent(state.dw, state.dcx);
  94.     glViewport(0, 0, state.width, state.height);
  95.     state.single = False;
  96.     XtUnmanageChild(state.sw);
  97.     break;
  98.     default:
  99.     break;
  100.     }
  101. }
  102.  
  103. static void
  104. menu(Widget w, XtPointer clientData, XtPointer callData) {
  105.     int entry = (int) clientData;
  106.  
  107.     switch (entry) {
  108.     case 0:
  109.     if (state.animate_wpid) {
  110.         XtRemoveWorkProc(state.animate_wpid);
  111.         state.animate_wpid = 0;
  112.     } else {
  113.         /* register work proc */
  114.         state.animate_wpid = XtAppAddWorkProc(state.appctx, redraw_proc, &state.dw);
  115.     }
  116.     break;
  117.     case 2:
  118.     exit(EXIT_SUCCESS);
  119.     break;
  120.     default:
  121.     break;
  122.     }
  123. }
  124.  
  125. static void
  126. activate_menu(Widget w, XtPointer clientData, XEvent *event, Boolean *cont) {
  127.     Widget popup = *((Widget *) clientData);
  128.  
  129.     if (event->type == ButtonPress && event->xbutton.button == Button3) {
  130.     XmMenuPosition(popup, &event->xbutton);
  131.     XtManageChild(popup);
  132.     }
  133. }
  134.  
  135. static void
  136. create_pulldown(Widget parent, int which) {
  137.     Arg args[10];
  138.     Widget pulldown;
  139.     int n;
  140.     XmButtonType button_types[] = {
  141.     XmRADIOBUTTON, XmRADIOBUTTON,
  142.     };
  143.     XmString button_labels[XtNumber(button_types)];
  144.  
  145.     button_labels[0] = XmStringCreateLocalized("single");
  146.     button_labels[1] = XmStringCreateLocalized("double");
  147.  
  148.     n = 0;
  149.     XtSetArg(args[n], XmNbuttonCount, XtNumber(button_types)); n++;
  150.     XtSetArg(args[n], XmNbuttonType, button_types); n++;
  151.     XtSetArg(args[n], XmNbuttons, button_labels); n++;
  152.     XtSetArg(args[n], XmNpostFromButton, 1); n++;
  153.     XtSetArg(args[n], XmNradioBehavior, True); n++;
  154.     XtSetArg(args[n], XmNsimpleCallback, submenu); n++;
  155.     pulldown = XmCreateSimplePulldownMenu(parent, "pulldown", args, n);
  156.  
  157.     XtSetArg(args[0], XmNset, True); /* initially double buffered */
  158.     XtSetValues(XtNameToWidget(pulldown, "button_1"), args, 1);
  159.  
  160.     XmStringFree(button_labels[0]);
  161.     XmStringFree(button_labels[1]);
  162. }
  163.  
  164. static void
  165. create_popup(Widget parent) {
  166.     Arg args[10];
  167.     static Widget popup;
  168.     int n;
  169.     XmButtonType button_types[] = {
  170.     XmCHECKBUTTON, XmCASCADEBUTTON, XmSEPARATOR, XmPUSHBUTTON,
  171.     };
  172.     XmString button_labels[XtNumber(button_types)];
  173.  
  174.     button_labels[0] = XmStringCreateLocalized("animate");
  175.     button_labels[1] = XmStringCreateLocalized("visual");
  176.     button_labels[2] = NULL;
  177.     button_labels[3] = XmStringCreateLocalized("quit");
  178.  
  179.     n = 0;
  180.     XtSetArg(args[n], XmNbuttonCount, XtNumber(button_types)); n++;
  181.     XtSetArg(args[n], XmNbuttonType, button_types); n++;
  182.     XtSetArg(args[n], XmNbuttons, button_labels); n++;
  183.     XtSetArg(args[n], XmNsimpleCallback, menu); n++;
  184.     popup = XmCreateSimplePopupMenu(parent, "foo", args, n);
  185.     XtAddEventHandler(parent, ButtonPressMask, False, activate_menu, &popup);
  186.     create_pulldown(popup, 0);
  187.  
  188.     XmStringFree(button_labels[0]);
  189.     XmStringFree(button_labels[1]);
  190.     XmStringFree(button_labels[3]);
  191. }
  192.  
  193. static void
  194. map_change(Widget w, XtPointer clientData, XEvent *event, Boolean *cont) {
  195.     switch (event->type) {
  196.     case MapNotify:
  197.     /* resume animation if we become mapped and are in the animated state */
  198.         if (state.animate_wpid != 0)
  199.          state.animate_wpid = XtAppAddWorkProc(state.appctx, redraw_proc, &state.dw);
  200.         break;
  201.     case UnmapNotify:
  202.     /* don't animate if we aren't mapped */
  203.         if (state.animate_wpid) XtRemoveWorkProc(state.animate_wpid);
  204.         break;
  205.     }
  206. }
  207.  
  208. main(int argc, char *argv[]) {
  209.     Display        *dpy;
  210.     XVisualInfo    *visinfo;
  211.     GLXContext      glxcontext;
  212.     Widget          toplevel, frame, form;
  213.     Arg            args[30];
  214.     int            n;
  215.  
  216.     toplevel = XtOpenApplication(&state.appctx, "switch-visual", NULL, 0, &argc, argv,
  217.         fallbackResources, applicationShellWidgetClass, NULL, 0);
  218.     dpy = XtDisplay(toplevel);
  219.  
  220.     frame = XmCreateFrame(toplevel, "frame", NULL, 0);
  221.     XtManageChild(frame);
  222.     form = XmCreateForm(frame, "form", NULL, 0);
  223.     XtManageChild(form);
  224.  
  225.     /* create single buffered widget & context */
  226.     if (!(visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), sb_attribs)))
  227.     XtAppError(state.appctx, "no suitable single buffered RGB visual");
  228.     /* attach to form on all 4 sides */
  229.     n = 0;
  230.     XtSetArg(args[n], XtNx, 10); n++;
  231.     XtSetArg(args[n], XtNy, 10); n++;
  232.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  233.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  234.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  235.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  236.     XtSetArg(args[n], GLwNvisualInfo, visinfo); n++;
  237.     state.sw = XtCreateWidget("single", glwMDrawingAreaWidgetClass,
  238.     form, args, n);
  239.     XtAddCallback(state.sw, GLwNexposeCallback, expose, NULL);
  240.     XtAddCallback(state.sw, GLwNresizeCallback, resize, NULL);
  241.     XtAddCallback(state.sw, GLwNinputCallback, input, NULL);
  242.     state.scx = glXCreateContext(dpy, visinfo, 0, GL_TRUE);
  243.  
  244.     /* create double buffered widget */
  245.     if (!(visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), db_attribs)))
  246.     XtAppError(state.appctx, "no suitable double buffered RGB visual");
  247.     XtSetArg(args[n-1], GLwNvisualInfo, visinfo);
  248.     state.dw = XtCreateManagedWidget("double", glwMDrawingAreaWidgetClass,
  249.     form, args, n);
  250.     XtAddCallback(state.dw, GLwNexposeCallback, expose, NULL);
  251.     XtAddCallback(state.dw, GLwNresizeCallback, resize, NULL);
  252.     XtAddCallback(state.dw, GLwNinputCallback, input, NULL);
  253.     state.dcx = glXCreateContext(dpy, visinfo, 0, GL_TRUE);
  254.  
  255.     create_popup(frame);
  256.  
  257.     XtAddEventHandler(toplevel, StructureNotifyMask, False, map_change, NULL);
  258.     XtRealizeWidget(toplevel);
  259.  
  260.     /* double buffered window on top */
  261.     XRaiseWindow(dpy, XtWindow(state.dw));
  262.  
  263.     state.direct = glXIsDirect(dpy, state.dcx);
  264.  
  265.     GLwDrawingAreaMakeCurrent(state.sw, state.scx);
  266.     initialize();
  267.     GLwDrawingAreaMakeCurrent(state.dw, state.dcx);
  268.     initialize();
  269.  
  270.     /* extract window dimensions for viewport */
  271.     XtVaGetValues(state.dw, XmNwidth, &state.width, XmNheight, &state.height);
  272.  
  273.     XtAppMainLoop(state.appctx);
  274. }
  275.  
  276. static void
  277. initialize(void) {
  278.     GLUquadricObj *cyl;
  279.  
  280.     glShadeModel(GL_FLAT);
  281.     gluPerspective(40., 1.0, 0.01, 1000.0);
  282.     glTranslatef(0.0, 0.0, -3.0);
  283.     glClearColor(0.2,0.2,0.2,0.);
  284.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  285.     cyl = gluNewQuadric();
  286.     glNewList(1, GL_COMPILE);
  287.     glPushMatrix();
  288.     glTranslatef(0., 0., -.5);
  289.     gluCylinder(cyl, 0.0, 0.4, 1.0, 25, 25);
  290.     glPopMatrix();
  291.     glEndList();
  292.     gluDeleteQuadric(cyl);
  293. }
  294.  
  295. static void
  296. draw_scene(Widget w, Boolean advance) {
  297.     static float rot = 90.;
  298.  
  299.     glClear(GL_COLOR_BUFFER_BIT);
  300.     glColor3f(.1, .1, .8);
  301.     glPushMatrix();
  302.     if (advance && (rot += 5.) > 360.) rot -= 360.;
  303.     glRotatef(rot,0.,1.,0.);
  304.     glCallList(1);
  305.     glPopMatrix();
  306.     if (!state.single) GLwDrawingAreaSwapBuffers(w);
  307.     if (!state.direct) glFinish();    /* hack to improve net interactivity */
  308. }
  309.  
  310. static Boolean
  311. redraw_proc(XtPointer clientData) {
  312.     Widget *w = (Widget *)clientData;
  313.     draw_scene(*w, True);
  314.     return False;
  315. }
  316.